﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Common;
using Common.Views;

namespace DataAccess
{
    public class ProductsRepository : ConnectionClass
    {
        public ProductsRepository() : base() { }

        public IQueryable<Product> GetAllProducts()
        {
            return Entity.Products;
        }

        public Product GetProduct(int id)
        {
            return Entity.Products.SingleOrDefault(p => p.ProductID == id);
        }

        public OrdersView GetProductDetails(int productID, Guid orderID)
        {
            return (
               from p in Entity.Products
               join od in Entity.OrderDetails
               on p.ProductID equals od.ProductID
               join o in Entity.Orders
               on od.OrderID equals o.OrderID

               where p.ProductID == productID
               && o.OrderID == orderID
               orderby o.OrderDate descending

               select new OrdersView()
               {
                   OrderID = o.OrderID,
                   ProductID = p.ProductID,
                   Features = p.Features,
                   Quantity = od.ProductQty,
                   OrderDate = o.OrderDate,
                   WarrantyExpiryDate = od.WarrantyExpiryDate
               }).First();
        }

        public IQueryable<CommentsProduct> GetCommentsForProduct(int id)
        {
            return Entity.CommentsProducts.Where(p => p.ProductID == id).AsQueryable();
        }

        public void AddToCart(Cart cart)
        {
            Entity.AddToCarts(cart);
            Entity.SaveChanges();
        }

        public Cart GetCart(string username, int productId)
        {
            return Entity.Carts.SingleOrDefault(u => u.Username == username && u.ProductID == productId);
        }

        public void UpdateCart(string username, int productId, int newQty)
        {
            Cart c = GetCart(username, productId);
            c.Quantity += newQty;
            Entity.SaveChanges();
        }

        public void AddComment(CommentsProduct cp)
        {
            Entity.CommentsProducts.AddObject(cp);
            Entity.SaveChanges();
        }

        public IQueryable<Cart> GetCartForUser(string username)
        {
            return Entity.Carts.Where(u => u.Username == username);
        }

        public IQueryable<CartView> GetProductsInShoppingCart(string username)
        {
            return (
                    from sc in Entity.Carts
                    join p in Entity.Products
                    on sc.ProductID equals p.ProductID
                    where sc.Username == username

                    select new CartView()
                    {
                        ProductID = p.ProductID,
                        ProductName = p.Name,
                        ProductImage = p.Image,
                        ProductPrice = p.Price,
                        ProductQuantity = sc.Quantity
                    }
                );
        }

        public void RemoveShoppingCart(Cart cart)
        {
            Entity.Carts.DeleteObject(cart);
            Entity.SaveChanges();
        }

        public void DecreaseStock(int productID, int qty)
        {
            Product p = (
                    from pr in Entity.Products
                    where pr.ProductID == productID
                    select pr
                ).SingleOrDefault();
            p.Stock -= qty;
            Entity.SaveChanges();
        }

        public IQueryable<int> GetRatingForProduct(int productId)
        {
            return (
                    from pr in Entity.ProductRatings
                    where pr.ProductID == productId
                    select pr.Rating
                );
        }

        public IQueryable<int> GetUserRatings(string username, int productId)
        {
            return (
                from pr in Entity.ProductRatings
                where pr.ProductID == productId
                && pr.Username == username
                select pr.Rating
                );
        }

        public void AddRatingForProduct(ProductRating pr)
        {
            Entity.ProductRatings.AddObject(pr);
            Entity.SaveChanges();
        }

        public IEnumerable<ProductCategory> GetProductCategories()
        {
            return Entity.ProductCategories;
        }

        /*public IQueryable<OrdersView> GetProductsByCategory(int categoryId)
        {
            return (
                    from p in Entity.Products
                    join f in Entity.Faults
                    on p.ProductID equals f.ProductID
                    join fd in Entity.FaultDetails
                    on f.FaultID equals fd.FaultID
                    join fs in Entity.FaultStatus
                    on fd.FaultStatusID equals fs.StatusID

                    where p.CategoryID == categoryId
                    select new OrdersView()
                    {
                        ProductName = p.Name,
                        Features = p.Features,
                        ImageLink = p.Image,
                        Quantity = p.Stock,
                        Price = p.Price,
                        DateListed = p.DateListed,
                        FaultStatus = fs.Status
                    }
                ).Distinct();
        }*/

        public IQueryable<Product> GetProductsByCategory(int categoryId)
        {
            return Entity.Products.Where(p => p.CategoryID == categoryId);
        }

        public IEnumerable<Product> GetProductByName(string keyword)
        {
            return Entity.Products.Where(p => p.Name.Contains(keyword));
        }

        public IEnumerable<Product> GetProductByPrice(decimal min, decimal max)
        {
            return Entity.Products.Where(p => (p.Price >= min) && (p.Price <= max));
        }

        public IEnumerable<Product> SortByPriceAsc()
        {
            return Entity.Products.OrderBy(p => p.Price);
        }

        public IEnumerable<Product> SortByPriceDesc()
        {
            return Entity.Products.OrderByDescending(p => p.Price);
        }

        public IEnumerable<Product> SortByDateAsc()
        {
            return Entity.Products.OrderByDescending(p => p.DateListed);
        }
    }
}
